package com.thread.threadfirst.studyThread4;

import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 10、第五种线程池：WorkStealingPool（偷线程池）
 * 比如线程池中有3个线程，每个线程都维护自己的一个队列，当一个线程执行完成它的队列中的所有任务后，就去其他线程维护的队列中偷一个任务来执行，是主动的。
 * 本质上是使用ForkJoinPool来实现的。
 * WorkStealingPool会默认根据CPU的核数起相应数量的线程。
 * WorkStealingPool是精灵线程daemon（即后台线程 守护线程），这种线程有一个特点：主线程结束后，它可能还在后台运行，是看不到任何输出的。如果想看到输出，就需要让主线程阻塞。
 * 而WorkStealingPool实际是用ForkJoinPool实现的，所以ForkJoinPool也是精灵线程daemon（即后台线程 守护线程）。
 * <p>
 * 精灵线程的好处：
 * 会在后台一直运行，只要虚拟机不退出，它就不会退出，只要有任务来，它就会一直执行。
 */
public class T_ThreadPool5 {
    public static void main(String[] args) throws IOException {
        ExecutorService service = Executors.newWorkStealingPool();  //注意：这里没有指定个数，因为WorkStealingPool会默认根据CPU的核数起相应数量的线程。
        System.out.println(Runtime.getRuntime().availableProcessors());  //输出CPU的核数 8核。

        //9个任务
        service.execute(new R(1000));
        service.execute(new R(2000));
        service.execute(new R(2000));
        service.execute(new R(2000));
        service.execute(new R(2000));
        service.execute(new R(2000));
        service.execute(new R(2000));
        service.execute(new R(2000));
        service.execute(new R(2000));

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(service);  //[Running, parallelism = 8, size = 8, active = 8, running = 2, steals = 4, tasks = 0, submissions = 0]
        //WorkStealingPool是精灵线程daemon（即后台线程 守护线程），这种线程有一个特点：主线程结束后，它可能还在后台运行，是看不到任何输出的。如果想看到输出，就需要让主线程阻塞。
        System.in.read();
    }

    static class R implements Runnable {
        int time;

        public R(int time) {
            this.time = time;
        }

        @Override
        public void run() {
            try {
                TimeUnit.MILLISECONDS.sleep(time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(time + " " + Thread.currentThread().getName());  //注意：输出的是ForkJoinPool，因为WorkStealingPool是用ForkJoinPool来实现的，相当于ForkJoinPool上面封装了一层就是WorkStealingPool了。
            //而且线程数默认是和CPU核数相等的，所以这里只有8个线程，而最后一个任务是由先完成任务的线程0来执行的。
        }
    }
}
